package com.bosicloud.cmb.ibp.aws.adapter.service.impl;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.PutObjectResult;
import com.bosicloud.cmb.ibp.aws.adapter.service.S3Service;
import com.bosicloud.cmb.ibp.commom.cdetector.CharsetDetector;
import com.bosicloud.cmb.ibp.commom.cdetector.CharsetMatch;
import com.bosicloud.cmb.ibp.commom.exception.BusinessException;
import com.bosicloud.cmb.ibp.commom.properties.AWSProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Objects;
import java.util.UUID;

/**
 * @author Jack Peng / ziliang.peng@bosicloud.com
 */
@Slf4j
@Service
public class S3ServiceImpl implements S3Service {


    private static final String JSON_SUFFIX = ".json";
    private static final String APPLICATION_JSON = "application/json;charset=UTF-8";
    private static final String IMAGE_PNG = "image/png";
    private static final String IMAGE_JPG = "image/jpg";
    private static final String IMAGE_SUFFIX = ".png";
    private static final String JPG_IMAGE_SUFFIX = ".jpg";

    @Autowired
    AmazonS3 amazonS3;

    @Autowired
    AWSProperties properties;

    @Override
    public String uploadFile(String fileName, byte[] data) {

        fileName = fileName.toLowerCase();

        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(chooseContentType(fileName));
        final String replaceName = replaceFileName2UUID(fileName);

        if (replaceName.endsWith(JSON_SUFFIX)) {
            final Charset charset = this.findCharset(data);

            log.debug("Detected charset: {}", charset);

            if (!"UTF-8".equalsIgnoreCase(charset.toString())) {
                data = new String(data, charset).getBytes();
                data = new String(data, Charset.forName("UTF-8")).getBytes();
            }
        }
        try {
            ByteArrayInputStream bis = new ByteArrayInputStream(data);
            PutObjectRequest pr = new PutObjectRequest(properties.getS3bucketName(), replaceName, bis, metadata).withCannedAcl(CannedAccessControlList.PublicRead);
            PutObjectResult result = amazonS3.putObject(pr);
            bis.close();
        } catch (IOException e) {
            throw new BusinessException(e.getMessage());
        }
        return amazonS3.getUrl(properties.getS3bucketName(), replaceName).toString();

    }

    private String chooseContentType(String fileName) {
        if (fileName.endsWith(JSON_SUFFIX)) {
            return APPLICATION_JSON;
        } else if (fileName.endsWith(IMAGE_SUFFIX)) {
            return IMAGE_PNG;
        } else if (fileName.endsWith(JPG_IMAGE_SUFFIX)) {
            return IMAGE_JPG;
        } else {
            throw new BusinessException("不支持当前媒体类型");
        }
    }

    private String replaceFileName2UUID(String fileName) {
        if (fileName.endsWith(JSON_SUFFIX)) {
            return UUID.randomUUID().toString().concat(JSON_SUFFIX);
        } else if (fileName.endsWith(IMAGE_SUFFIX)) {
            return UUID.randomUUID().toString().concat(IMAGE_SUFFIX);
        }
        else if (fileName.endsWith(JPG_IMAGE_SUFFIX)) {
            return UUID.randomUUID().toString().concat(JPG_IMAGE_SUFFIX);
        }else {
            throw new BusinessException("不支持的文件类型.");
        }
    }


    private Charset findCharset(final byte[] bytes) {
        final CharsetDetector charsetDetector = new CharsetDetector();
        charsetDetector.setText(bytes);
        final CharsetMatch charsetMatch = charsetDetector.detect();
        if (Objects.isNull(charsetMatch)) {
            throw new BusinessException("不支持该文件编码.");
        }
        try {
            return Charset.forName(charsetMatch.getName());
        } catch (Exception e) {
            throw new BusinessException(e.getMessage());
        }
    }

}
